#include <thread>
#include <thread>
#include <iostream>

using namespace std;

template<class T>
class SmartPtr
{
public:
	SmartPtr(T* ptr)
		:_ptr(ptr)
	{}

	~SmartPtr()
	{
		cout << "delete :" << _ptr << endl;
		delete _ptr;
	}

	T* operator->()
	{
		return _ptr;
	}

	T& operator*()
	{
		return *_ptr;
	}

private:
	T* _ptr;
};

int div()
{
	int a, b;
	cin >> a >> b;
	if (b == 0)
		throw invalid_argument("除0错误");

	return a / b;
}

void f()
{
	SmartPtr<pair<string, string>> sp1(new pair<string, string>("111", "222"));
	SmartPtr<pair<string, string>> sp2(new pair<string, string>);

	cout << sp1->first << endl;
	cout << sp1->second << endl;

	sp2 = sp1;

	try 
	{
		div();
	}
	catch (...)
	{
		throw;
	}

}

//int main()
//{
//	try
//	{
//		f();
//	}
//	catch (const exception& e)
//	{
//		cout << e.what() << endl;
//	}
//
//	return 0;
//}

//int main()
//{
//	SmartPtr<pair<string, string>> sp1(new pair<string, string>("111", "222"));
//	SmartPtr<pair<string, string>> sp2(new pair<string, string>);
//
//	sp2 = sp1;
//
//
//	return 0;
//}

#include <memory>

#include "SmartPtr.h"

class A
{
public:
	A(int a)
		:_a(a)
	{
	}

	~A()
	{
		cout << "~A()" << endl; //方便查看调用
	}

	int _a;
};

//int main()
//{
//	//xyx::auto_ptr<A> ap1(new A(1));
//	//xyx::auto_ptr<A> ap2(new A(2));
//
//	//xyx::auto_ptr<A> ap3 = ap1;
//
//	//
//	////ap1->_a++;//访问悬空指针，导致程序崩溃
//
//	//xyx::unique_ptr<A> up1(new A(3));
//	////std::unique_ptr<A> up2(up1); //禁止拷贝
//
//	xyx::shared_ptr<A> sp1(new A(3));
//	xyx::shared_ptr<A> sp2(new A(2));
//	xyx::shared_ptr<A> sp3(sp1);
//	xyx::shared_ptr<A> sp4 = sp3;
//
//	sp1 = sp1;
//
//
//	sp1->_a++;
//	sp3->_a++;
//
//	cout << sp3->_a << endl;
//
//	return 0;
//}

//struct Node
//{
//	A data = 1;
//	xyx::weak_ptr<Node> _next = xyx::weak_ptr<Node>();
//	xyx::weak_ptr<Node> _prev = xyx::weak_ptr<Node>();
//};
//
//int main()
//{
//	xyx::shared_ptr<Node> sp1(new Node);
//	xyx::shared_ptr<Node> sp2(new Node);
//	cout << sp1.use_count() << endl;// use_count获取引用计数个数
//	cout << sp2.use_count() << endl;
//
//	sp1->_next = sp2;
//	cout << sp1.use_count() << endl; 
//
//	sp2->_prev = sp1;
//	cout << sp2.use_count() << endl;
//
//	return 0;
//}

struct Date
{
	int _year = 0;
	int _month = 0;
	int _day = 0;
};
void SharePtrFunc(xyx::shared_ptr<Date>& sp, size_t n, mutex& mtx)
{
	cout << sp.get() << endl;
	for (size_t i = 0; i < n; ++i)
	{
		// 这里智能指针拷贝会++计数，智能指针析构会--计数，这里是线程安全的。
		xyx::shared_ptr<Date> copy(sp);
		// 这里智能指针访问管理的资源，不是线程安全的。所以我们看看这些值两个线程++了2n
		//次，但是最终看到的结果，并一定是加了2n
		{
		unique_lock<mutex> lk(mtx);
		copy->_year++;
		copy->_month++;
		copy->_day++;
		}
	}
}
int main()
{
	xyx::shared_ptr<Date> p(new Date);
	cout << p.get() << endl;
	const size_t n = 100000;
	mutex mtx;
	thread t1(SharePtrFunc, std::ref(p), n, std::ref(mtx));
	thread t2(SharePtrFunc, std::ref(p), n, std::ref(mtx));
	t1.join();
	t2.join();
	cout << p->_year << endl;
	cout << p->_month << endl;
	cout << p->_day << endl;
	cout << p.use_count() << endl;
	return 0;
}